#include "push_pdo.h"

extern void push_db_data(string addr, string query, string error, long execute_micro_time);

void push_pdo_handler(zend_execute_data *execute_data_ptr, long execute_micro_time, string class_name, string function_name)
{
    // 初始化参数
    string host = "127.0.0.1";
    string port = "3306";
    string addr = "";
    string sql = "";
    string err = "";
    string query = "";

    // 获取数据库连接地址
    zval *obj = execute_data_ptr->object;
    pdo_dbh_t *dbh = (pdo_dbh_t *)zend_object_store_get_object(obj TSRMLS_CC);
    string dsn = dbh->data_source;
    vector<string> dsn_attrs = split(dsn, ";");
    for (auto attr : dsn_attrs)
    {
        vector<string> kv = split(attr, "=");
        if (kv[0] == "host")
        {
            host = kv[1];
        }
        if (kv[0] == "port")
        {
            port = kv[1];
        }
    }

    addr = host + ":" + port;

    // 获取参数值
    zval *arg = func_get_arg(execute_data_ptr, 1);
    if (arg != nullptr && Z_TYPE_P(arg) == IS_STRING)
    {
        string statement = Z_STRVAL_P(arg);
        vector<string> sql_str = split(statement, " ");
        sql = sql_str[0];
    }

    // 获取错误信息
    pdo_stmt_t *stmt = dbh->query_stmt;
    pdo_error_type *pdo_err = &dbh->error_code;
    zval error_value;
    array_init(&error_value);
    add_next_index_string(&error_value, *pdo_err, 1);
    if (dbh->methods->fetch_err)
    {
        dbh->methods->fetch_err(dbh, stmt, &error_value);
        zval **value;
        if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(&error_value), 2, (void **)&value))
        {
            err = Z_STRVAL_PP(value);
        }
    }

    query = class_name + "->" + function_name + "::" + sql;

    push_db_data(addr, query, err, execute_micro_time);
}

void push_pdo_stmt_handler(zend_execute_data *execute_data_ptr, long execute_micro_time, string class_name, string function_name)
{
    // 初始化参数
    string host = "127.0.0.1";
    string port = "3306";
    string addr = "";
    string sql = "";
    string err = "";
    string query = "";
    
    // 获取数据库连接地址
    zval *obj = execute_data_ptr->object;
    pdo_stmt_t *stmt = (pdo_stmt_t *)zend_object_store_get_object(obj TSRMLS_CC);
    pdo_dbh_t *dbh = stmt->dbh;
    string dsn = dbh->data_source;
    vector<string> dsn_attrs = split(dsn, ";");
    for (auto attr : dsn_attrs)
    {
        vector<string> kv = split(attr, "=");
        if (kv[0] == "host")
        {
            host = kv[1];
        }
        if (kv[0] == "port")
        {
            port = kv[1];
        }
    }

    addr = host + ":" + port;

    // 获取函数传参
    string sql_string = stmt->query_string;
    vector<string> sql_str = split(sql_string, " ");
    sql = sql_str[0];

    // 获取错误信息
    pdo_error_type *pdo_err = &dbh->error_code;
    zval error_value;
    array_init(&error_value);
    add_next_index_string(&error_value, *pdo_err, 1);
    if (dbh->methods->fetch_err)
    {
        dbh->methods->fetch_err(dbh, stmt, &error_value);
        zval **value;
        if (SUCCESS == zend_hash_index_find(Z_ARRVAL_P(&error_value), 2, (void **)&value))
        {
            err = Z_STRVAL_PP(value);
        }
    }

    query = string(class_name) + "->" + string(function_name) + "::" + sql;

    push_db_data(addr, query, err, execute_micro_time);
}